import json
import os
import re

from kea2.hypiumDriver import HDriver

from kea2.utils import getLogger, TimeStamp

TIME_STAMP = TimeStamp().getTimeStamp()

import os
import datetime
import re
from jinja2 import Environment, FileSystemLoader


logger = getLogger(__name__)


def generate_html_report(output_dir, result_file, test_duration=None, test_app=None):
    """Generate HTML report to display test results and error screenshots
    
    Args:
        output_dir: Output directory path
        result_file: Result JSON file path
        test_duration: Test duration in seconds (optional)
        test_app: Test application package name (optional)
    """
    error_message = None
    
    # Ensure screenshots directory exists
    screenshots_path = os.path.join(output_dir, "screenshots")
    if not os.path.exists(screenshots_path):
        os.makedirs(screenshots_path)
    
    # Read test result data
    results = {}
    try:
        if os.path.exists(result_file):
            with open(result_file, 'r', encoding='utf-8') as f:
                results = json.load(f)
        else:
            # If result file doesn't exist, create a basic result file
            error_message = f"Result file {result_file} does not exist, creating empty result"
            logger.warning(error_message)
            # Check if directory exists
            result_dir = os.path.dirname(result_file)
            if not os.path.exists(result_dir):
                os.makedirs(result_dir)
            # Create an empty result file
            with open(result_file, 'w', encoding='utf-8') as f:
                json.dump({}, f)
    except Exception as e:
        error_message = f"Failed to read result file: {str(e)}"
        logger.error(error_message)
        results = {}
    
    # Calculate overall statistics
    total_stats = {
        "total_properties": len(results),
        "executed_properties": 0,
        "failed_properties": 0,
        "error_properties": 0
    }
    
    for prop_stats in results.values():
        # Count properties that were executed (executed > 0)
        if prop_stats.get("executed", 0) > 0:
            total_stats["executed_properties"] += 1
        
        # Count properties that had failures (fail > 0)
        if prop_stats.get("fail", 0) > 0:
            total_stats["failed_properties"] += 1
            
        # Count properties that had errors (error > 0)
        if prop_stats.get("error", 0) > 0:
            total_stats["error_properties"] += 1
    
    # Format test duration
    duration_info = None
    if test_duration is not None:
        hours = int(test_duration // 3600)
        minutes = int((test_duration % 3600) // 60)
        seconds = int(test_duration % 60)
        
        if hours > 0:
            duration_info = {
                "total_seconds": test_duration,
                "formatted": f"{hours}小时{minutes}分钟{seconds}秒",
                "display": f"{hours:02d}:{minutes:02d}:{seconds:02d}"
            }
        elif minutes > 0:
            duration_info = {
                "total_seconds": test_duration,
                "formatted": f"{minutes}分钟{seconds}秒",
                "display": f"{minutes:02d}:{seconds:02d}"
            }
        else:
            duration_info = {
                "total_seconds": test_duration,
                "formatted": f"{seconds}秒",
                "display": f"{seconds}秒"
            }

    # Get all screenshot files
    screenshot_files = []
    if os.path.exists(screenshots_path):
        screenshot_files = [f for f in os.listdir(screenshots_path) if f.endswith(('.png', '.jpg', '.jpeg'))]
    
    # Process screenshot information
    screenshots = []
    for screenshot_file in screenshot_files:
        try:
            # Extract property name and timestamp from screenshot filename
            # Typical format: module.class.method_timestamp.extension
            # or explore_test.exploreCase.test_swipe_left_should_exit_2025061216_3056797456.jpeg
            
            # Remove file extension
            filename_without_ext = os.path.splitext(screenshot_file)[0]
            
            # Try to extract timestamp pattern and split accordingly
            timestamp_pattern = r'_(\d{10,})_(\d+)$'
            timestamp_match = re.search(timestamp_pattern, filename_without_ext)
            
            if timestamp_match:
                # Remove timestamp part to get property name
                prop_name = filename_without_ext[:timestamp_match.start()]
                timestamp_str = timestamp_match.group(1)
                
                # Try to format timestamp if it's in the expected format
                timestamp = None
                if len(timestamp_str) >= 10:
                    try:
                        # Try to parse as YYYYMMDDHH format
                        year = timestamp_str[:4]
                        month = timestamp_str[4:6]
                        day = timestamp_str[6:8]
                        hour = timestamp_str[8:10]
                        minute = timestamp_str[10:12] if len(timestamp_str) >= 12 else "00"
                        timestamp = f"{year}-{month}-{day} {hour}:{minute}"
                    except:
                        timestamp = timestamp_str
            else:
                # Fallback: assume everything before the last timestamp-like pattern is property name
                parts = filename_without_ext.split('_')
                # Look for timestamp-like patterns and remove them
                prop_parts = []
                for part in parts:
                    if not re.match(r'^\d{8,}$', part):  # Skip pure numeric parts that look like timestamps
                        prop_parts.append(part)
                prop_name = '_'.join(prop_parts) if prop_parts else filename_without_ext
                timestamp = None
            
            screenshots.append({
                "filename": screenshot_file,
                "prop_name": prop_name,
                "timestamp": timestamp
            })
            
            # If no test result but have screenshots, create test result entry from screenshot name
            if prop_name not in results and '.' in prop_name:
                results[prop_name] = {
                    "precond_satisfied": 1,
                    "executed": 1,
                    "fail": 1,
                    "error": 0
                }
        except Exception as e:
            logger.error(f"Error processing screenshot {screenshot_file}: {str(e)}")
            # Fallback: use filename without extension as property name
            screenshots.append({
                "filename": screenshot_file,
                "prop_name": os.path.splitext(screenshot_file)[0],
                "timestamp": None
            })
    
    # Get device information
    device_info = None
    try:
        if HDriver and hasattr(HDriver, 'getDeviceSerial'):
            device_sn = HDriver.getDeviceSerial()
            if device_sn:
                device_info = {
                    "sn": device_sn
                }
    except Exception as e:
        logger.error(f"Failed to get device information: {str(e)}")
    
    # Use Jinja2 to render template
    try:
        # Get template directory path
        template_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
        env = Environment(loader=FileSystemLoader(template_dir))
        template = env.get_template('bug_report.html')
        
        # Render template
        html_content = template.render(
            timestamp=TIME_STAMP,
            generation_time=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            results=results,
            screenshots=screenshots,
            total_stats=total_stats if total_stats["executed_properties"] > 0 else None,
            device_info=device_info,
            error_message=error_message,
            test_duration=duration_info,
            test_app=test_app
        )
        
        # Write HTML file
        report_path = os.path.join(output_dir, "bug_report.html")
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        
        logger.info(f"HTML report generated: {report_path}")
        return report_path
    
    except Exception as e:
        error_msg = f"Failed to render template: {str(e)}"
        logger.error(error_msg)